package com.windward.vii.service.apple;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sun.jersey.api.client.ClientResponse;
import com.windward.vii.common.Constants;
import com.windward.vii.common.JsonResult;
import com.windward.vii.common.ResultCode;
import com.windward.vii.config.ApplePayConfig;
import com.windward.vii.dao.entity.AssetUserRecharge;
import com.windward.vii.dao.entity.Goods;
import com.windward.vii.dao.entity.Order;
import com.windward.vii.dao.mapper.AssetPlatformAccountMapper;
import com.windward.vii.dao.mapper.AssetUserAccountMapper;
import com.windward.vii.dao.mapper.AssetUserRechargeMapper;
import com.windward.vii.dao.mapper.OrderMapper;
import com.windward.vii.service.GoodsService;
import com.windward.vii.service.OrderService;
import com.windward.vii.utils.HttpRestClient;
import com.windward.vii.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import javax.annotation.Resource;
import java.util.Date;

@Component
public class ApplePayService {

    private static Logger logger = LoggerFactory.getLogger(ApplePayService.class);

    //sandbox 开发环境
    public static final String URL_VERIFY_RECEIPT_SANDBOX = "https://sandbox.itunes.apple.com/verifyReceipt";
    //prod 生产环境
    public static final String URL_VERIFY_RECEIPT = "https://buy.itunes.apple.com/verifyReceipt";

    @Resource
    OrderService orderService;
    @Autowired
    PlatformTransactionManager transactionManager;
    @Resource
    GoodsService goodsService;
    @Resource
    OrderMapper orderMapper;
    @Resource
    AssetUserAccountMapper assetUserAccountMapper;
    @Resource
    AssetUserRechargeMapper assetUserRechargeMapper;
    @Resource
    AssetPlatformAccountMapper assetPlatformAccountMapper;
    @Resource
    ApplePayConfig applePayConfig;

//    public JsonResult verify(Long uid, String orderSn, String receiptData) {
//        Order order = orderService.selectBySn(orderSn);
//        if(order == null) {
//            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "购买订单不存在");
//        }
//        if(!uid.equals(order.getUid())) {
//            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "支付订单与支付用户不匹配");
//        }
//        order.setOutTradeNo(receiptData);
//
//        // 更新订单状态为：已支付、待发货
//        Order updateOrder = new Order();
//        updateOrder.setId(order.getId());
//        updateOrder.setOutTradeNo(receiptData); // 苹果回执订单号
//        updateOrder.setStatus(Constants.Order.ORDER_STATUS_PAY_SUCCESS);
//        updateOrder.setPayStatus(Constants.Order.PAY_STATUS_SUCCESS);
//        updateOrder.setPayTime(new Date());
//        updateOrder.setDeliverStatus(Constants.Order.DELIVER_STATUS_AWAITING);
//        updateOrder.setUpdateTime(new Date());
//        if(orderService.updateByPrimaryKeySelective(updateOrder) < 1) {
//            return JsonResult.error("更新订单状态失败");
//        }
//
//        // 尝试IAP验证一次，超时时间为5秒，成功的话直接充值，不成功让Task自动处理。
//        return verifyReceipt(order);
//    }

    public JsonResult verify(Long uid, String goodsSn, String receiptData, String ip) {
        Goods goods = goodsService.getBySn(goodsSn);
        if (goods == null) {
            return new JsonResult(ResultCode.PARAM_ERROR_CODE, "购买商品不存在");
        }

        Order order = orderMapper.selectByOutTradeNo(receiptData);
        if(order != null && order.getDeliverStatus() == Constants.Order.DELIVER_STATUS_SUCCESS) {
            return JsonResult.success("该票据已充值成功");
        }

        if(order == null) {
            JsonResult<Order> orderResult = orderService.createOrderForApplePay(uid, goods, receiptData, ip);
            if (orderResult.getCode() != ResultCode.SUCCESS_CODE) {
                return orderResult;
            }
            order = orderResult.getBody();
        }

        // 尝试IAP验证一次，超时时间为5秒，成功的话直接充值，不成功让Task自动处理。
        String url = applePayConfig.isSandbox() ? URL_VERIFY_RECEIPT_SANDBOX : URL_VERIFY_RECEIPT;
        return verifyReceipt(order, url);
    }


    private JsonResult verifyReceipt(Order order, String url) {
        logger.info(" >> 开始IAP验票 order = {}", JSON.toJSONString(order));
        // receipt-data
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("receipt-data", order.getOutTradeNo());
        ClientResponse response = HttpRestClient.post(url, jsonObject.toString());

        // 客户端支付，调用服务器接口，传递receipt-data和orderSn；
        // 服务端，把订单状态设置为已支付，待配送状态
        // Task定时扫描，1. 调用 apple verifyReceipt 接口验证；2. 修改订单状态，并充值虚拟币；
        if(response == null) {
            logger.error("苹果支付验证API请求失败(response is null)，请重试");
            return new JsonResult(ResultCode.ERROR_CODE, "苹果支付验证API请求失败(response is null)，请重试");
        }
        String content = response.getEntity(String.class);
        if(StringUtils.isBlank(content)) {
            logger.error("苹果支付验证API请求失败(content is blank)，请重试");
            return new JsonResult(ResultCode.ERROR_CODE, "苹果支付验证API请求失败(content is blank)，请重试");
        }
        JSONObject responseJson = JSON.parseObject(content);
        if(responseJson == null) {
            logger.error("苹果支付验证API请求失败(response is invalidate json)，请重试");
            return new JsonResult(ResultCode.ERROR_CODE, "苹果支付验证API请求失败(response is invalidate json)，请重试");
        }
        if(!responseJson.containsKey("status")) {
            logger.error("ERROR_CODE_701，IAP返回数据错误(status is blank)，验证失败");
            return new JsonResult(ResultCode.ERROR_CODE_701, "IAP返回数据错误(status is blank)，验证失败");
        }
        logger.info("IAP返回数据：responseJson = {}", responseJson);
        // 判断状态
        Integer status = responseJson.getInteger("status");
        // 验证成功
        if(status == 0) {
            // 验证订单号和金额
            JSONObject receipt = responseJson.getJSONObject("receipt");
            if(receipt != null) {
                if(!receipt.containsKey("in_app")) {
                    Response1 response1 = JSON.parseObject(content, Response1.class);
                    Receipt1 receipt1 = response1.getReceipt();
                    if(receipt1 != null) {
                        logger.info("IAP返回数据：handle response1 logic");
                        String product_id = receipt1.getProduct_id();
                        if(order.getGoodsSn().equals(product_id)) {
                            logger.info(" >> IAP验票成功");
                            JsonResult result = addCoinToUserAccount(order);
                            if(result.getCode() != ResultCode.SUCCESS_CODE) {
                                logger.error("addCoinToUserAccount error：JsonResult = {}", result.toString());
                            } else {
                                logger.info("addCoinToUserAccount success：JsonResult = {}", result.toString());
                            }
                            return result;
                        } else {
                            logger.error("ERROR_CODE_702，订单号与IAP订单号不符");
                            return new JsonResult(ResultCode.ERROR_CODE_702, "订单号与IAP订单号不符");
                        }
                    }
                } else {
                    Response2 response2 = JSON.parseObject(content, Response2.class);
                    Receipt2 receipt2 = response2.getReceipt();
                    if(receipt2 != null && receipt2.getIn_app() != null) {
                        logger.info("IAP返回数据：handle response2 logic");
                        InApp inApp = receipt2.getIn_app();
                        String product_id = inApp.getProduct_id();
                        if(order.getGoodsSn().equals(product_id)) {
                            logger.info(" >> IAP验票成功");
                            JsonResult result = addCoinToUserAccount(order);
                            if(result.getCode() != ResultCode.SUCCESS_CODE) {
                                logger.error("addCoinToUserAccount error：JsonResult = {}", result.toString());
                            } else {
                                logger.info("addCoinToUserAccount success：JsonResult = {}", result.toString());
                            }
                            return result;
                        } else {
                            logger.error("ERROR_CODE_702，订单号与IAP订单号不符");
                            return new JsonResult(ResultCode.ERROR_CODE_702, "订单号与IAP订单号不符");
                        }
                    }
                }
            }
            return new JsonResult(ResultCode.ERROR_CODE_701, "IAP返回数据错误，验证失败");
        } else if(status == 21007) { // 服务器去验证的时候先调生成环境的url,如果报错了21007,再去回调沙盒测试环境的url验证
            return verifyReceipt(order, URL_VERIFY_RECEIPT_SANDBOX);
        } else {
            logger.error("IAP返回数据：responseJson = {}", responseJson);
            return new JsonResult(status, "IAP返回数据错误，验证失败");
        }
    }


    private JsonResult addCoinToUserAccount(Order order) {
        logger.info(" >> 开始充值：uid={}, coin={}", order.getUid(), order.getCoin());
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(def);

        boolean isRechargeSuccess = false;

        try {
            // select for update，防止重复充值
            Order dbOrder = orderMapper.selectByPrimaryKeyForUpdate(order.getId());
            if(dbOrder.getDeliverStatus() == Constants.Order.DELIVER_STATUS_SUCCESS) {
                isRechargeSuccess = true;
                return JsonResult.success("该票据已充值成功");
            }

            // 更新订单状态
            Order updateOrder = new Order();
            updateOrder.setId(order.getId());
            updateOrder.setStatus(Constants.Order.ORDER_STATUS_DELIVER_SUCCESS);
            updateOrder.setUpdateTime(new Date());
            updateOrder.setDeliverStatus(Constants.Order.DELIVER_STATUS_SUCCESS);
            updateOrder.setDeliverTime(new Date());
            if(orderMapper.update4Deliver(updateOrder) < 1) {
                logger.error("更新订单状态失败");
                return JsonResult.error("更新订单状态失败");
            }

            // 生成充值成功记录
            AssetUserRecharge assetUserRecharge = new AssetUserRecharge();
            assetUserRecharge.setUid(order.getUid());
            assetUserRecharge.setOrderId(order.getId());
            assetUserRecharge.setPayType(order.getPayType());
            assetUserRecharge.setAmount(order.getAmount());
            assetUserRecharge.setCoin(order.getCoin());
            assetUserRecharge.setTerminalType(order.getTerminalType());
            assetUserRecharge.setCreateTime(new Date());
            if(assetUserRechargeMapper.insertSelective(assetUserRecharge) < 1) {
                logger.error("生成充值成功记录失败");
                return JsonResult.error("生成充值成功记录失败");
            }

            // 添加账户虚拟币
            if(assetUserAccountMapper.recharge(order.getUid(), order.getCoin()) < 1) {
                logger.error("添加账户余额失败");
                return JsonResult.error("添加账户余额失败");
            }

            // 添加系统账户余额
            if(assetPlatformAccountMapper.recharge(order.getAmount()) < 1) {
                logger.error("添加系统账户余额失败");
                return JsonResult.error("添加系统账户余额失败");
            }

            logger.info(" >> 充值成功：uid={}, coin={}", order.getUid(), order.getCoin());
            isRechargeSuccess = true;
            return JsonResult.success();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(" >> addCoinToUserAccount exception ：sn={}, e={}", order.getSn(), e.getMessage());
            return JsonResult.error("充值回调发生异常");
        } finally {
            if(isRechargeSuccess) {
                transactionManager.commit(status);
            } else {
                transactionManager.rollback(status);
            }
        }
    }

}
